Carbon

     

Creating Dialog Boxes That Yield

An easy thing to do with the Thread Manager is to free your application to do useful work in the background while waiting for a user to respond to a dialog box that is displayed on the screen. The way to do this is to handle the dialog box in the main thread and to put a call in the dialog's event filter function that yields control to other threads that can do useful work while the dialog box is displayed. Listing 8 shows the code to implement such a dialog box.

Listing 8  Creating a dialog box that yields

pascal boolean DoYieldFilter (DialogPtr theDialogPtr, EventRecord *theEvent, 
                                      short *theItemHit)
 {
    /* Yield to whomever wants to run. */
    YieldToAnyThread();
    /* Call the standard filter procedure defined in Dialogs.h. */
    return (MyStdFilterProc(theDialogPtr, theEvent, theItemHit));
 }
 /* The DoOKDialog function just handles a simple OK dialog box. */
 void DoOKDialog (short dialogID)
 {
    DialogPtr theDialog;
    short  itemHit;
    GrafPtr  savePort;
    OSErr  theError;
    
    GetPort(&savePort);
    
    if ((theDialog = GetNewDialog(dialogID, NULL, (Ptr)-1)) != NULL)
    {
        SetPort(theDialog);
        ShowWindow(theDialog);
        do
        {
            ModalDialog(DoYieldFilter, &itemHit);
        } while (itemHit != okButton);
        DisposDialog(theDialog);
    } else
        DebugStr("\pCould not find dialog");
    SetPort(savePort);
 }

In Listing 8, DoOKDialog is a function that handles an OK dialog box. It calls the Dialog Manager ModalDialog function to display the dialog box. The ModalDialog function calls an event filter procedure, DoYieldFilter . This procedure makes two calls; one to YieldToAnyThread and the other to MyStdFilterProc. The call to YieldToAnyThread enables your application to keep working while the dialog box is displayed. It yields control to any threads that are waiting to execute. Each waiting thread that executes in turn, of course, also has a yield call in it, so control eventually returns to DoYieldFilter .

When control returns, DoYieldFilter calls another event filter procedure, MyStdFilterProc. If no events have occurred, it simply returns to the ModalDialog function, which loops through again and calls the DoYieldFilter function, enabling the working threads to gain control again. If an event does occur, MyStdFilterProc handles it and returns the result to ModalDialog . When a user chooses the OK or Cancel button, ModalDialog exits the loop.

Keep in mind that when an operating-system event occurs, the Thread Manager always returns control to the main thread at the first scheduling opportunity. This means that if there are several threads in your application doing background work while the dialog box is being displayed, at the first scheduling opportunity after an operating-system event occurs (and if the yield or other call causing the reschedule does not specify a particular thread to schedule next), the Thread Manager schedules the main thread no matter which threads are ahead of it in the scheduling queue. For this reason it is best to put event handling functions in the main thread.


© 2000 Apple Computer, Inc. – (Last Updated 09 May 00)